#include <cstddef>
#include <iostream>
#include <bitset>
#include "../source/public.h"

static framework::Logger::ptr g_logger = FRAMEWORK_LOG_ROOT();

void testByteArray111()
{
    std::vector<int32_t> vec;
    for(int i = 0; i < 10; ++i)
    {
        vec.push_back(i);
    }
    framework::ByteArray::ptr byteArray(new framework::ByteArray(1));
    for(auto& t : vec)
    {
        byteArray->writeInt32(t);
    }
    byteArray->setPosition(0);
    for(size_t i = 0; i < vec.size(); ++i)
    {
        int32_t t = byteArray->readInt32();
        // FRAMEWORK_ASSERT(t == vec[i]);
        std::cout << "t = " << t << "\ttt = " << std::bitset<32>(t) << std::endl;
    }
}


void testByteArray()
{
    #define XX(type, len, write_fun, read_fun, base_len)    \
    {                                                       \
        std::vector<type> vec;                              \
        for(int i = 0; i < len; ++i)                        \
        {                                                   \
            vec.push_back(i);                               \
        }                                                   \
        framework::ByteArray::ptr byteArray(new framework::ByteArray(base_len));    \
        for(auto& t : vec)                                  \
        {                                                   \
            byteArray->write_fun(t);                        \
        }                                                   \
        byteArray->setPosition(0);                          \
        std::cout << #type << ": ";                         \
        for(size_t i = 0; i < vec.size(); ++i)              \
        {                                                   \
            type t = byteArray->read_fun();                 \
            std::cout << std::bitset<8>(t) << "\t";         \
            std::cout << "t = " << t << "\t";               \
        }                                                   \
        std::cout << std::endl;                             \
    }                                                       \



    XX(int8_t,  10, writeFint8, readFint8, 1);
    XX(uint8_t, 10, writeFuint8, readFuint8, 1);
    XX(int16_t,  10, writeFint16,  readFint16, 1);
    XX(uint16_t, 10, writeFuint16, readFuint16, 1);
    XX(int32_t,  10, writeFint32,  readFint32, 1);
    XX(uint32_t, 10, writeFuint32, readFuint32, 1);
    XX(int64_t,  10, writeFint64,  readFint64, 1);
    XX(uint64_t, 10, writeFuint64, readFuint64, 1);

    XX(int32_t,  10, writeInt32,  readInt32, 1);
    XX(uint32_t, 10, writeUint32, readUint32, 1);
    XX(int64_t,  10, writeInt64,  readInt64, 1);
    XX(uint64_t, 10, writeUint64, readUint64, 1);
#undef XX

}

void testFile()
{
    #define XX(type, len, write_fun, read_fun, base_len)    \
    {                                                       \
        std::vector<type> vec;                              \
        for(int i = 0; i < len; ++i)                        \
        {                                                   \
            vec.push_back(i);                               \
        }                                                   \
        framework::ByteArray::ptr byteArray(new framework::ByteArray(base_len));         \
        for(auto& t : vec)                                  \
        {                                                   \
            byteArray->write_fun(t);                        \
        }                                                   \
        byteArray->setPosition(0);                          \
        std::cout << #type << ": ";                         \
        for(size_t i = 0; i < vec.size(); ++i)              \
        {                                                   \
            type t = byteArray->read_fun();                 \
            std::cout << "t = " << t << "\t";               \
        }                                                   \
        std::cout << std::endl;                             \
        byteArray->setPosition(0);   /*test file*/          \
        byteArray->writeToFile("./" #type "_" #len "-" #read_fun ".dat");                          \
        framework::ByteArray::ptr byteArray2(new framework::ByteArray(base_len * 2));    \
        byteArray2->readFromFile("./" #type "_" #len "-" #read_fun ".dat");                        \
        byteArray2->setPosition(0);                                                      \
        std::cout << "===byteArray: " << byteArray->toString();                             \
        std::cout << "===byteArray2: " << byteArray2->toString();                           \
    }                                                                                    
    
    XX(int8_t,  10, writeFint8, readFint8, 1);

#undef XX
}


void test1111()
{
    #define XX(type, len, write_fun, read_fun, base_len) {\
    std::vector<type> vec; \
    for(int i = 0; i < len; ++i) { \
        vec.push_back(rand()); \
    } \
    framework::ByteArray::ptr ba(new framework::ByteArray(base_len)); \
    for(auto& i : vec) { \
        ba->write_fun(i); \
    } \
    ba->setPosition(0); \
    for(size_t i = 0; i < vec.size(); ++i) { \
        type v = ba->read_fun(); \
        FRAMEWORK_ASSERT(v == vec[i]); \
    } \
    FRAMEWORK_ASSERT(ba->getReadSize() == 0); \
    FRAMEWORK_LOG_INFO(g_logger) << #write_fun "/" #read_fun \
                    " (" #type " ) len=" << len \
                    << " base_len=" << base_len \
                    << " size=" << ba->getSize(); \
    ba->setPosition(0); \
    FRAMEWORK_ASSERT(ba->writeToFile("./" #type "_" #len "-" #read_fun ".dat")); \
    framework::ByteArray::ptr ba2(new framework::ByteArray(base_len * 2)); \
    FRAMEWORK_ASSERT(ba2->readFromFile("./" #type "_" #len "-" #read_fun ".dat")); \
    ba->setPosition(0); \
    ba2->setPosition(0); \
    FRAMEWORK_ASSERT(ba->toString() == ba2->toString()); \
    FRAMEWORK_ASSERT(ba->getPosition() == 0); \
    FRAMEWORK_ASSERT(ba2->getPosition() == 0); \
}
    XX(int8_t,  100, writeFint8, readFint8, 1);
    XX(uint8_t, 100, writeFuint8, readFuint8, 1);
    XX(int16_t,  100, writeFint16,  readFint16, 1);
    XX(uint16_t, 100, writeFuint16, readFuint16, 1);
    XX(int32_t,  100, writeFint32,  readFint32, 1);
    XX(uint32_t, 100, writeFuint32, readFuint32, 1);
    XX(int64_t,  100, writeFint64,  readFint64, 1);
    XX(uint64_t, 100, writeFuint64, readFuint64, 1);

    XX(int32_t,  100, writeInt32,  readInt32, 1);
    XX(uint32_t, 100, writeUint32, readUint32, 1);
    XX(int64_t,  100, writeInt64,  readInt64, 1);
    XX(uint64_t, 100, writeUint64, readUint64, 1);

#undef XX
}

int main(void)
{
    // testByteArray111();
    // testByteArray();
    // test();
    // testFile();
    test1111();

    std::cout << "test ok\n";

    return 0;
}
